/*
 * 弹框组件
 * @param target 弹出框内容元素
 * @param type 弹框类型:popup,nohead,notitle,noclose,nofoot
 * @param template 页面中模板位置ID
 * @param width 弹出框宽度 0 或'auto'为不限制
 * @param height 弹出框高度 0 或'auto'为不限制
 * @param title 弹出框标题
 * @param autoHide 是否一定时间自动关闭 false或具体数值(秒)
 * @param onLoad 载入时触发事件
 * @param onShow 显示时触发事件
 * @param onClose 关闭时触发事件
 * @param modal 是否在弹出时候其他区域不可操作
 * @param pins 是否把弹窗固定不动
 * @param single 单一窗口，还是多层窗口
 * @param effect 是否使用特效 false true or {style from to}
 * @param position 定位到哪里
 * 		target 相对定位的目标
 * 		to 相对定位基点x,y(九点定位:0/left/right/100%/center/50%,0/top/bottom/100%/center/50%)
 * 		base 弹框的定位基点x,y(同上)
 * 		offset 偏移目标位置
 * 			x 横向偏移
 * 			y 纵向偏移
 * 		intoView 如果超出可视范围，是否滚动使之可见
 * @param useIframeShim 是否使用iframe遮盖
 * @param async 异步调用方式: false, frame, ajax
 * @param frameTpl iframe方式调用的模板
 * @param ajaxTpl ajax方式调用的模板
 * @param asyncOptions 异步请求的参数
 * 		method 请求的方式
 * 		data 请求的数据
 * 		onSuccess 请求成功后执行
 * 		onError 请求失败后执行
 * @param component 弹出框的构成组件
 * @method getTemplate 获取模板
 * @method setTemplate 处理设置模板
 * @method maxSize 使窗口最大化
 * @return this Popup element
 */
var Popup = new Class({
	Implements: [Events, Options],
	options: {
		type: 'popup',
        template: null,
		width: 0,
		height: 0,
		title: LANG_shopwidgets.tip,
        autoHide: false,
		/* onLoad: function(){},
		 * onShow: function(){},
		 * onClose: function(){},*/
		modal: false,
		pins: false,
		single: false,
		minHeight:220,
		minWidth:250,
		effect: {
			style: 'opacity',
			duration: 400,
			from: 0,
			to: 1
		},
		position: {
			target: document.body,
			base: {x: 'center',	y: 'center'},
			to: {x: 'center',	y: 'center'},
			offset: {x: 0, y: 0},
            intoView: false
		},
        useIframeShim: false,
		async: false,
        frameTpl: '<iframe allowtransparency="allowtransparency" align="middle" frameborder="0" height="100%" width="100%" scrolling="auto" src="about:blank"></iframe>',
        ajaxTpl: '<div class="loading">loading...</div>',
		asyncOptions: {
			method: 'get',
			data: '',
			onSuccess: function() {},
			onError: function() {}
		},
		component: {
			container: 'popup-container',
			body: 'popup-body',
			header: 'popup-header',
			close: 'popup-btn-close',
			content: 'popup-content',
			mask: 'popup-modalMask'
		}
	},
	initialize: function(target, options) {
		if (!target) return;
        this.target = target;
		this.setOptions(options);
		options = this.options;

		var popUp = this.popUp = this.setTemplate(options.template);
		var el = new Element('div');
		this.body = popUp.getElement('.' + options.component.body) || el;
		this.header = popUp.getElement('.' + options.component.header) || el;
		this.close = popUp.getElement('.' + options.component.close) || el;
		this.content = popUp.getElement('.' + options.component.content) || el;
		this.size = {
			x: options.width.toInt() ? options.width.toInt() : '',
			y: options.height.toInt() ? options.height.toInt() : ''
		};
		if (!popUp.retrieve('instance')) this.body.setStyles({
			width: this.size.x,
			height: this.size.y
		});
        if (!options.title) this.header.getElement('h2') && this.header.getElement('h2').destroy();
        if (typeOf(target) === 'string') {
            if (options.async === 'ajax') {
                new Request.HTML({
                    url: target + '',
                    update: this.content,
                    method: options.asyncOptions.method,
                    data: options.asyncOptions.data,
                    onSuccess: options.asyncOptions.onSuccess.bind(this),
                    onFailure: options.asyncOptions.onError.bind(this)
                }).send();
                if(!this.size.y && popUp.getSize().y >= document.body.getSize().y){
                    this.size.y = Math.min(options.minHeight.toInt(), document.body.getSize().y);
                    $(this.body).setStyle('height', this.size.y - this.popUp.getPatch().y);
                }
            }
            else this.content.getElement('iframe').set('src', target).addEvent('load', this.options.asyncOptions.onSuccess.bind(this));
        }
		if (options.modal) {
			this.mask = new Mask({
				'class': options.component.mask,
				'effect': options.effect
			});
		}
		this.attach(); //执行初始化加载
	},
	getTemplate: function(template, type) {
        var options = this.options;
        template = template || options.template;
        if (template && typeOf(template) === 'string') {
			if(!document.id(template)) return template;
			template = $(template);
		}
        if (typeOf(template) === 'element' && (/^(?:script|textarea)$/i).test(template.tagName.toLowerCase())) return $(template).get('value') || $(template).get('html');
		type = type || options.type;
		var popUpTpl = [
			'<div class="{body}">',
			'<div class="{header}">',
			'<h2>{title}</h2>',
			'<span><button type="button" class="{close}" title="关闭" hidefocus><i>×</i></button></span>',
			'</div>',
			'<div class="{content}">{main}</div>',
			'</div>'
		];
		if (type === 'nohead') popUpTpl[1] = popUpTpl[2] = popUpTpl[3] = popUpTpl[4] = '';
		else if (type === 'notitle') popUpTpl[2] = '';
		else if (type === 'noclose' || !!options.autoHide) popUpTpl[3] = '';

        return popUpTpl.join('\n');
	},
    setTemplate: function(template) {
        var options = this.options,
            single = document.getElement('[data-single=true].' + options.component.container),
            main = '';

        if(options.single && single) return single;

        template = '<div class="{container}" data-single="'+ !!options.single +'">' + this.getTemplate(template) + '</div>';
        if (typeOf(this.target) === 'element') {
            main = this.target.get('html');
        }
        else if (typeOf(this.target) === 'string') {
            main = options.async === 'ajax' ? options.ajaxTpl : options.frameTpl;
        }

		var component = Object.merge(options.component, {
			title: options.title,
			main: main
		});
        return new Element('div', {html: template.substitute(component)}).getFirst().inject(document.body);
    },
	attach: function() {
		this.fireEvent('load', this);
		this.show();
		//绑定关闭事件
		var closeBtn = this.popUp.getElements('.' + this.options.component.close);
		if (closeBtn.length) closeBtn.addEvent('click', this.hide.bind(this));
		this.popUp.store('instance', this);
	},
    position: function(){
        var options = this.options, element;
		//if (this.popUp.retrieve('instance')) return;
        if (!this.size.x && Browser.ie && Browser.version < 8 && (this.body.getSize().x >= window.getSize().x)) this.body.setStyle('width', this.options.minWidth.toInt());
        if (this.size.y) element = this.popUp;
        else if(this.popUp.getSize().y >= document.body.getSize().y) element = document.body;
        if(typeOf(element) === 'element') this.setHeight(element);
        this.popUp.position(options.position);
        if (options.pins) this.popUp.pin();
    },
	setHeight: function(el) {
		this.content.setStyle('height', el.getSize().y - this.popUp.getPatch().y - $(this.body).getPatch().y - $(this.header).outerSize().y - this.content.getPatch().y);
	},
	//弹出可见
	show: function() {
        if(this.displayed) return this;
        this.popUp.setStyle('display', 'block');

		if(Browser.ie6 && this.options.useIframeShim) {
			new Element('iframe', {
				src: 'about:blank',
				style: 'position:absolute;z-index:-1;border:0 none;filter:alpha(opacity=0);top:-' + (this.popUp.getPatch().y || 0) + ';left:-' + (this.popUp.getPatch().x || 0) + ';width:' + (this.popUp.getSize().x || 0) + 'px;height:' + (this.popUp.getSize().y || 0) + 'px;'
			}).inject(this.popUp);
		}

		this.position();
		var eff = this.options.effect;
		if(eff) {
			if(eff === true || eff.style === 'opacity') this.popUp.setOpacity(eff.from || 0);
			new Fx.Tween(this.popUp, {duration: eff.duration || 400}).start(eff.style || 'opacity', eff.from || 0, eff.to || 1);
		}
		this.displayed = true;
		this.fireEvent('show', this);

		if (this.mask) this.mask.show();
        if (this.options.autoHide) this.hide.delay(this.options.autoHide.toInt() * 1000, this);

		return this;
	},
	//弹出隐藏
	hide: function() {
        if (!this.displayed) return this;
		this.fireEvent('close', this);
		if (this.options.pins) this.popUp.pin(false, false, false);
        if (this.options.single) {
            this.popUp.setStyle('display', 'none');
            this.displayed = false;
            this.mask && this.mask.hide();
            return this;
        }
		var eff = this.options.effect;
		if(eff) {
          	new Fx.Tween(this.popUp, {
				duration: eff.duration || 400,
				onComplete: function(){
					this.popUp.destroy();
				}.bind(this)
			}).start(eff.style || 'opacity', eff.to || 1, eff.from || 0);
		}
		else {
			this.popUp.destroy();
		}
		this.displayed = false;
		if (this.mask && ($$('.' + this.options.component.container).every(function(el) {
			return !this.displayed;
		}.bind(this)))) this.mask.hide();
        return this;
	},
	toElement: function() {
		return this.popUp;
	}
});

// pin
(function(){
	Element.implement({
		pin: function(enable, forceScroll, restore){
			//if(this.getStyle('display') == 'none') this.setStyle('display', '');
			if (enable !== false){
				if (!this.retrieve('pin:_pinned')){
					var scroll = window.getScroll();
					this.store('pin:_original', this.getStyles('position', 'top', 'left'));
					var pinnedPosition = this.getPosition(!Browser.ie6 ? document.body : this.getOffsetParent());
					var currentPosition = {
						left: pinnedPosition.x - scroll.x,
						top: pinnedPosition.y - scroll.y
					};
					if (!Browser.ie6){
						this.setStyle('position', 'fixed').setStyles(currentPosition);
					} else {
						if(!!forceScroll) this.setPosition({
							x: this.getOffsets().x + scroll.x,
							y: this.getOffsets().y + scroll.y
						});
						if (this.getStyle('position') == 'static') this.setStyle('position', 'absolute');

						var position = {
							x: this.getLeft() - scroll.x,
							y: this.getTop() - scroll.y
						};
						var scrollFixer = function(){
							if (!this.retrieve('pin:_pinned') || this.getStyle('left').toInt() >= document.body.clientWidth || this.getStyle('top').toInt() >= document.body.clientHeight) return;
							var scroll = window.getScroll();
							this.setStyles({
								left: position.x + scroll.x,
								top: position.y + scroll.y
							});
						}.bind(this);

						this.store('pin:_scrollFixer', scrollFixer);
						window.addEvent('scroll', scrollFixer);
					}
					this.store('pin:_pinned', true);
				}
			} else {
				if (!this.retrieve('pin:_pinned')) return this;
				if(!!restore) this.setStyles(this.retrieve('pin:_original', {}));
				this.eliminate('pin:_original');
				this.store('pin:_pinned', false);
				if (Browser.ie6) {
					window.removeEvent('scroll', this.retrieve('pin:_scrollFixer'));
					this.eliminate('pin:_scrollFixer');
				}
			}
			return this;
		},
		togglePin: function(){
			return this.pin(!this.retrieve('pin:_pinned'));
		}
	});
}).call(this);

//Mask
var Mask = new Class({
	Implements: [Options, Events],
	options: {
		target:null,
		'class': 'mask',
		width: 0,
		height: 0,
		effect: {
			style: 'opacity',
			duration: 400,
			from: 0,
			to: 0.3
		}
	},
	initialize: function(options) {
		this.target = (options && options.target) || document.id(document.body);
		//this.target.store('mask', this);
		this.setOptions(options);

		this.element = $$('div[rel=mask].' + this.options['class'])[0] || new Element('div[rel=mask].' + this.options['class']).inject(this.target);
		this.hidden = true;
	},
	setSize: function() {
		$(this.element).setStyles({
			width: this.options.width.toInt() || Math.max(this.target.getScrollSize().x, this.target.getSize().x, this.target.clientWidth),
			height: this.options.height.toInt() || Math.max(this.target.getScrollSize().y, this.target.getSize().y, this.target.clientHeight)
		});
	},
	show: function() {
		if (!this.hidden) return;
		window.addEvent('resize', this.setSize.bind(this));
		this.setSize();

		this.element.setStyle('display','block');
		var eff = this.options.effect;
		if(eff) {
			this.opacity = this.element.get('opacity');
			if(eff === true || eff.style == 'opacity') this.element.setOpacity(eff.from || 0);
			new Fx.Tween(this.element,{duration:eff.duration || 400}).start(eff.style || 'opacity', eff.from || 0, this.opacity);
		}
		this.hidden = false;
	},
	hide: function() {
		if (this.hidden) return;
		window.removeEvent('resize', this.setSize.bind(this));

		var eff = this.options.effect;
		if(eff) {
			new Fx.Tween(this.element, {
				duration:eff.duration || 400,
				onComplete: function(){
					this.element.setStyle('display','none');
				}.bind(this)
			}).start(eff.style || 'opacity', this.opacity, eff.from || 0);
		}
		else {
			this.element.setStyle('display','none');
		}
		this.hidden = true;
	},
	toggle: function() {
		this[this.hidden ? 'show' : 'hide']();
	}
});

var Ex_Dialog = new Class({
	Extends: Popup,
	initialize: function(target,options){
		options = Object.merge({
			width:330,
			template: $('popup-template'),
			position: {
				intoView: true
			}
		}, options || {});
		this.parent(target,options);
	}
});
Ex_Dialog.alert = function(msg, title) {
    var html = '<div class="message-main"><div class="figure"><dfn class="alert">alert!</dfn><span class="mark">' + msg + '</span></div> <div class="bottom"> <button type="button" class="popup-btn-close"><i><i>确定</i></i></button> </div></div>';
    new Ex_Dialog(new Element('div', {html: html}), {
		width: 400,
		title: title || '提示',
		modal: true,
		pins: true,
		single: true,
		effect: false,
		position: {
            intoView: true
		}
    });
};
Ex_Dialog.confirm = function(msg, callback) {
    var html = '<div class="message-main"><div class="figure"><dfn class="confirm">confirm!</dfn><span class="mark">' + msg + '</span></div> <div class="bottom"><button type="button" class="btn-confirm" data-return="1"><i><i>确认</i></i></button>　 <button type="button" class="btn-cancel" data-return="0"><i><i>取消</i></i></button></div></div>';
    new Ex_Dialog(new Element('div', {html: html}), {
		width: 400,
		title: '请确认',
		modal: true,
		pins: true,
		single: true,
		effect: false,
		position: {
            intoView: true
		},
        onLoad: function() {
            var _this = this, _return;
            this.content.getElements('[data-return]').addEvent('click', function(e){
                _return = !!this.get('data-return').toInt();
                _this.hide();
                callback && callback.call(this, _return);
            });
        }
    });
};

//Tips
var Ex_Tip = new Class({
    Extends: Popup,
    /*options: {
        intoView: true,
		onShow: function(){},
		onClose: function(){}
    },*/
    initialize: function(msg,options){
        if(!msg) return;
        options = options || {};
        var target = new Element('div[html=' + msg + ']');
        var relative = options.relative || document.body,
			rel = (/^(?:body|html)$/i).test(relative.tagName.toLowerCase()),
            x = rel ? 'center' : 0,
            y = rel ? 0 : 'top',
            pins = !!rel,
            offsetY = rel ? 0 : 'bottom';

        this.options = Object.merge(this.options, {
            type: options.type || 'nofoot',
            template: options.template || $('xtip-template'),
            modal: false,
            pins: pins,
            single: false,
            effect: true,
            position: {
                target: relative,
                to: {x: x, y: y},
				base: {x: 0, y: offsetY},
                offset: {
                    x: options.offset && options.offset.x ? options.offset.x : 0,
                    y: options.offset && options.offset.y ? options.offset.y : 0
                },
                intoView: options.intoView !== undefined ? options.intoView : true
            },
            component: {
                container: 'xtip-container',
                body: 'xtip-body',
                header: 'xtip-header',
                close: 'xtip-close',
                content: 'xtip-content'
            }
        });
        this.parent(target, options);
    }
});

/*
 * tooltips,需要在元素上添加自定义属性"data-tip"
 */
var Ex_Tips = function(elements, msg) {
	elements = $(elements) || $$('[data-tip]');
	if(!elements || !elements.length) return null;
	//build elements
	var container = $('xtips-container') || new Element('div', {
        html: '<div id="xtips-container" class="xtips-container"><i class="xtips-arr">◆</i><i class="xtips-arr2">◆</i><div id="xtips-content"></div></div>'
    }).getFirst().inject(document.body);
    var content = $('xtips-content');

	return elements.addEvents({
		mouseenter: function() {
			var text = msg || this.get('data-tip');
            if(!text) return;
			content.set('text', text); // set message
			//position it and set width?
			var position = this.getPosition(),
				size = container.getSize();
			container.setStyle('display', 'block').setStyles({
				left: Math.max(position.x - 4, 0),
				top: Math.max(position.y - container.getSize().y - 6, 0),
				width: this.get('data-tip-width') ? this.get('data-tip-width') : container.getSize().x > window.getSize().x ? window.getSize().x : '',
				opacity: 0
			}).tween('opacity', 0, Browser.ie6 ? 1 : 0.95);
		},
		mouseleave: function() {
			container.tween('opacity', Browser.ie6 ? 1 : 0.95, 0);
		}
	});
};
Element.implement({
    tips: function(msg){
        return Ex_Tips(this, msg);
    }
});
window.addEvent('domready', function(){
    Ex_Tips();
});

//Message box
function Message(msg, type, delay, template){
    if(!msg) return;
    if(typeOf(type) === 'number') {
        delay = type;
    }
    else {
        type = type || 'show';
        delay = delay || 5;
    }
    var component = {
        container: 'x' + type +'-container',
        body: 'x' + type +'-body',
        // header: 'x' + type +'-header',
        content: 'x' + type +'-content'
    };
    new Ex_Tip(msg, {
		type: 'nohead',
        template: template || $('xshow-template'),
        autoHide: delay,
        component: component
    });
}
Message.show = function(msg, delay) {
    Message(msg || LANG_jstools['messageShow'], 'error', delay);
};
Message.error = function(msg, delay) {
    Message(msg || LANG_jstools['messageError'], 'error', delay);
    return false;
};
Message.success = function(msg, delay) {
    Message(msg || LANG_jstools['messageSuccess'], 'success', delay);
    return true;
};

/*var Dropmenu = new Class({
	Extends: Popup,
	initialize: function(content, options){
		if(!content) return;
		var offset = {x: 0, y: 0};
		options = Object.merge({
			type: 'nohead',
			template: $('dropmenu-template'),
			position: {
				target: $(options.relative),
				base: {x: 0, y: 0},
				to: {x: 0, y: 'bottom'},
                intoView: 'in'
			},
            component: {
                container: 'x-dropmenu-container',
                body: 'x-dropmenu-body',
                content: 'x-dropmenu-content'
            },
			useIframeShim: true
		}, options || {});

		this.parent($(content), options);
	}
});
function dropMenu(el, content, options) {
    if(!$(el) || !content) return;
    options = options || {};
    switch (options.eventType) {
    case 'click':
        el.addEvent(options.eventType, function(){
            if(!this.retrieve('_dropmenu_')){
                var menu = new Dropmenu(content, options);
                menu.popUp.setStyle('font-size', '14px');
                this.store('_dropmenu_', menu);
            }
            else {
                this.retrieve('_dropmenu_').hide();
                this.eliminate('_dropmenu_');
            }
        });
        break;
    case 'mouseover':
        el.addEvents({
            'mouseover': function(){
                var menu = new Dropmenu(content, options);
                menu.popUp.setStyle('font-size', '14px');
                this.store('_dropmenu_', menu);
            },
            'mouseout': function(){
                this.retrieve('_dropmenu_').hide();
                this.eliminate('_dropmenu_');
            }
        });
        break;
    }
}*/
